﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Windows;

namespace GSdk.Shared.Windows.Properties
{
    public struct Property<T>
    {
        Property(DependencyProperty prop)
        {
            m_DependencyProperty = prop;
        }

        readonly DependencyProperty m_DependencyProperty;

        public static implicit operator Property<T>(PropertyBase prop)
        {
            return new Property<T>(prop.DependencyProperty);
        }

        public static implicit operator DependencyProperty(Property<T> prop)
        {
            return prop.m_DependencyProperty;
        }

        public T this[DependencyObject obj]
        {
            get { return (T)obj.GetValue(m_DependencyProperty); }
            set { obj.SetValue(m_DependencyProperty, value); }
        }
    }

    public abstract class PropertyBase
    {
        public readonly DependencyProperty DependencyProperty;

        protected PropertyBase(DependencyProperty prop)
        {
            DependencyProperty = prop;
        }
    }

    public sealed class Property<TContainer, TValue> : PropertyBase
    {
        public Property(Expression<Func<TContainer, TValue>> accessor)
            : base(DependencyProperty.Register(accessor.MemberToString(), typeof(TValue), typeof(TContainer)))
        {
        }
        public Property(Expression<Func<TContainer, TValue>> accessor, PropertyMetadata metadata)
            : base(DependencyProperty.Register(accessor.MemberToString(), typeof(TValue), typeof(TContainer), metadata))
        {
        }
        public Property(Expression<Func<TContainer, TValue>> accessor, PropertyMetadata metadata, ValidateValueCallback callback)
            : base(DependencyProperty.Register(accessor.MemberToString(), typeof(TValue), typeof(TContainer), metadata, callback))
        {
        }
    }

    public sealed class AttachedProperty<TContainer, TValue> : PropertyBase
    {
        public AttachedProperty(Expression<Func<Property<TValue>>> accessor)
            : base(DependencyProperty.RegisterAttached(accessor.MemberToString().Substring(0,accessor.MemberToString().Length - "Property".Length), typeof(TValue), typeof(TContainer)))
        {
        }
        public AttachedProperty(Expression<Func<Property<TValue>>> accessor, PropertyMetadata metadata)
            : base(DependencyProperty.RegisterAttached(accessor.MemberToString().Substring(0, accessor.MemberToString().Length - "Property".Length), typeof(TValue), typeof(TContainer), metadata))
        {
        }
        public AttachedProperty(Expression<Func<Property<TValue>>> accessor, PropertyMetadata metadata, ValidateValueCallback callback)
            : base(DependencyProperty.RegisterAttached(accessor.MemberToString().Substring(0, accessor.MemberToString().Length - "Property".Length), typeof(TValue), typeof(TContainer), metadata, callback))
        {
        }
    }
}
